"""飞书配置文件

此文件包含所有与飞书相关的配置：
1. 基础连接配置
2. 表格URL列表
3. 表名映射规则
4. 命名规则和处理函数
"""
import re
from typing import Dict, List, Set, Any

#=============================================================================
# 一、基础配置（需要修改）
#=============================================================================
# 飞书应用基础配置（必须设置）
FEISHU_CONFIG = {
    'app_id': 'cli_a785e873ef1e100b',        # 飞书应用ID
    'app_secret': 'i4pkJXtGjC4uN31v5ZGcLeaUij7FGA1h',  # 飞书应用密钥
    'app_token': 'S4UJb7v0oa1bkosWw7dcEVpsnRh',  # 飞书多维表应用token
    'timeout': 30  # 请求超时时间，单位秒
}

# 多维表格URL列表（根据需要修改）
FEISHU_TABLE_URLS = [
    "https://wx6lpdt35j.feishu.cn/base/S4UJb7v0oa1bkosWw7dcEVpsnRh?table=tblvpF1mcn10hcDa&view=vewAwXzPYj",  # 缺陷管理表
    "https://wx6lpdt35j.feishu.cn/base/S4UJb7v0oa1bkosWw7dcEVpsnRh?table=tblBr9sbIz8wEWdd&view=vewAwXzPYj"
    # 添加更多表格URL
]

#=============================================================================
# 二、表名处理规则（可按需修改）
#=============================================================================
# 表名手动映射配置（可选）
# 格式: "表ID": "数据库表名"
TABLE_NAME_MAPPING = {
    # 示例: "tblvpF1mcn10hcDa": "defect_management",  # 缺陷管理表
}

# 表名处理规则
TABLE_NAMING_RULES = {
    # 前缀配置 - 如果表名为非字母开头，添加此前缀
    "prefix": "t_",
    
    # 指定特定的表ID和表名的强制映射，优先级高于API获取的表名
    "force_mapping": {
        # "tblvpF1mcn10hcDa": "defect_management",  # 缺陷管理表
    },
    
    # 是否将中文和特殊字符替换为下划线
    "replace_non_ascii": True,
    
    # 是否同时保留表的原始字符与处理后字符
    "keep_original_name": False,
    
    # 最大表名长度，0表示不限制
    "max_name_length": 64,
}

#=============================================================================
# 三、API获取的表名缓存（程序运行时使用，无需修改）
#=============================================================================
# API获取的表名缓存，避免重复调用API
_TABLE_NAME_CACHE = {}

#=============================================================================
# 四、函数实现（无需修改）
#=============================================================================
def parse_feishu_url(url: str) -> Dict[str, str]:
    """从飞书多维表格URL中解析出app_token和table_id
    
    Args:
        url: 飞书多维表URL
        
    Returns:
        包含app_token和table_id的字典
    
    Raises:
        ValueError: URL解析失败
    """
    try:
        base_part = url.split('?')[0]
        app_token = base_part.split('/')[-1]
        query_params = url.split('?')[1]
        table_id = None
        for param in query_params.split('&'):
            if param.startswith('table='):
                table_id = param.split('=')[1]
                break
        if not app_token or not table_id:
            raise ValueError("无法从URL中解析出app_token或table_id")
        return {
            'app_token': app_token,
            'table_id': table_id
        }
    except Exception as e:
        raise ValueError(f"URL解析失败: {str(e)}")

def get_all_table_configs() -> List[Dict[str, str]]:
    """获取所有多维表格的配置信息
    
    Returns:
        表配置列表，每个配置包含app_token、table_id和table_name
    """
    table_configs = []
    for url in FEISHU_TABLE_URLS:
        config = parse_feishu_url(url)
        table_name = TABLE_NAME_MAPPING.get(config['table_id'], f"feishu_table_{config['table_id']}")
        config['table_name'] = table_name
        table_configs.append(config)
    return table_configs

def get_api_table_name_mapping(force_refresh: bool = False) -> Dict[str, str]:
    """根据API获取表名映射
    
    这个函数会调用飞书API获取所有表的真实名称，并返回映射字典。
    结果会被缓存，避免重复调用API。
    
    Args:
        force_refresh: 是否强制刷新缓存
        
    Returns:
        表ID到表名的映射字典
    """
    global _TABLE_NAME_CACHE
    
    # 如果已有缓存且不强制刷新，直接返回缓存
    if _TABLE_NAME_CACHE and not force_refresh:
        return _TABLE_NAME_CACHE
    
    # 首先尝试直接解析URL列表，获取所有应用token
    all_tables = TABLE_NAME_MAPPING.copy()
    
    try:
        # 动态导入，避免循环引用
        from services.feishu_service import FeishuService
        from utils.logger import sync_logger
        
        # 获取所有应用的表
        feishu_service = FeishuService()
        
        # 解析URL列表，获取所有应用token
        app_tokens = set()
        for url in FEISHU_TABLE_URLS:
            try:
                config = parse_feishu_url(url)
                app_tokens.add(config['app_token'])
            except Exception as e:
                sync_logger.log_error(f"解析URL失败: {url}, 错误: {str(e)}")
                continue
        
        # 遍历所有应用，获取其中的表
        for app_token in app_tokens:
            try:
                sync_logger.log_info(f"开始获取应用 {app_token} 的表列表")
                tables = feishu_service.get_all_tables(app_token)
                sync_logger.log_info(f"成功获取到 {len(tables)} 张表")
                
                for table in tables:
                    table_id = table.get('id', '')
                    if not table_id:
                        continue
                        
                    # 生成表名并处理特殊字符
                    table_name = table.get('name', '')
                    if table_name:
                        # 处理表名，移除特殊字符，只保留中文、英文、数字和下划线
                        import re
                        table_name = re.sub(r'[^\w\u4e00-\u9fff]', '_', table_name)
                        # 确保表名以字母开头（MySQL要求）
                        if table_name and (not table_name[0].isalpha()):
                            table_name = f"t_{table_name}"
                            
                        # 如果表名不存在，则使用默认名称
                        if not table_name:
                            table_name = f"feishu_table_{table_id}"
                            
                        # 保存到映射字典
                        all_tables[table_id] = table_name
                        sync_logger.log_info(f"成功获取到表信息: ID={table_id}, 表名={table_name}")
            except Exception as e:
                sync_logger.log_error(f"获取应用 {app_token} 的表列表失败: {str(e)}")
                # 继续处理下一个应用，不中断整个流程
                continue
        
        # 更新缓存
        _TABLE_NAME_CACHE = all_tables
        sync_logger.log_info(f"成功更新表名映射缓存, 共 {len(all_tables)} 张表")
        
        return all_tables
    except Exception as e:
        sync_logger.log_error(f"API获取表名映射失败: {str(e)}")
        # 如果API获取失败，则返回已有的缓存
        return all_tables

def process_table_name(table_id: str, table_name: str) -> str:
    """根据规则处理表名
    
    Args:
        table_id: 表ID
        table_name: 原始表名
        
    Returns:
        处理后的表名
    """
    # 1. 直接映射优先
    if table_id in TABLE_NAMING_RULES["force_mapping"]:
        return TABLE_NAMING_RULES["force_mapping"][table_id]
    
    # 如果没有表名，使用默认命名
    if not table_name:
        return f"feishu_{table_id}"
    
    # 2. 处理非字母名称
    processed_name = table_name
    
    # 3. 处理特殊字符
    processed_name = re.sub(r'[^\w\u4e00-\u9fff]', '_', processed_name)
    
    # 4. 处理中文字符（默认不再替换中文，保留原始中文内容）
    # 这里修改为默认保留中文内容
    if TABLE_NAMING_RULES["replace_non_ascii"] == True:
        # 只处理特殊符号，保留中文
        pass
    
    # 5. 如果不是字母开头，添加前缀（数字或中文开头都会添加前缀）
    if not re.match(r'^[a-zA-Z]', processed_name):
        processed_name = f"{TABLE_NAMING_RULES['prefix']}{processed_name}"
    
    # 6. 限制字符数
    max_length = TABLE_NAMING_RULES["max_name_length"]
    if max_length > 0 and len(processed_name) > max_length:
        processed_name = processed_name[:max_length]
    
    return processed_name

def get_table_name(table_id: str) -> str:
    """获取表的名称，优先使用API获取的表名，失败则使用配置映射或默认名称
    
    Args:
        table_id: 表ID
        
    Returns:
        表名
    """
    # 尝试从API获取
    raw_table_name = ""
    api_mapping = get_api_table_name_mapping()
    if table_id in api_mapping and api_mapping[table_id]:
        raw_table_name = api_mapping[table_id]
    
    # 其次使用静态配置
    if not raw_table_name and table_id in TABLE_NAME_MAPPING:
        raw_table_name = TABLE_NAME_MAPPING[table_id]
    
    # 最后使用默认名称
    if not raw_table_name:
        raw_table_name = f"feishu_table_{table_id}"
    
    # 应用命名规则
    return process_table_name(table_id, raw_table_name)


# 使用说明：
# 1. 请在飞书开发者平台(https://open.feishu.cn/app)创建应用并获取app_id和app_secret
# 2. 确保应用已启用"多维表格"权限
# 3. 在多维表格中获取table_id和app_token (在多维表URL中可以找到)
# 示例：FEISHU_CONFIG = {
#    'app_id': 'cli_9e8f7d6c5b4a3',
#    'app_secret': 'hMtDPcGaK8YvB5ZqX4WmE1Nn3bLpTrFs',
#    'app_token': 'bascnz4NqPeqX5UyP1cstknxxf',
#    'table_id': 'tblEnTq234JKCL',
#    'timeout': 30
# } 